﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Universum.Infrastructure.Persistence;
using Universum.Infrastructure.Persistence.Queries.Classes;
using Universum.Model.Domain.Classes;
using System.Security.Principal;

namespace Universum.Model.Services.Classes
{
	public class PageGroupServiceImpl : IPageGroupService
	{
		IRepository _Repository;
		IPrincipal _Principal;
		ILabWorkArticleService _LabWorkArticleService;
		IPageArticleService _PageArticleService;
		public PageGroupServiceImpl(
			IPrincipal principal,
			IRepository repository,
			ILabWorkArticleService labWorkArticleService,
			IPageArticleService pageArticleService)
		{
			_Repository = repository;
			_Principal = principal;
			_LabWorkArticleService = labWorkArticleService;
			_PageArticleService = pageArticleService;

		}
		#region IPageGroupService Members

		public void SaveOrUpdate(Universum.Model.Domain.Classes.PageGroup pageGroup)
		{
			if (not_owner(pageGroup)) return;
			if (pageGroup.Order == 0)
				pageGroup.Order = GetPageGroupsByClassIdAndParentGroupId(pageGroup.ClassId, pageGroup.ParentGroupId).Count() + 1;

			_Repository.SaveOrUpdate(pageGroup);
		}

		private bool not_owner(PageGroup pageGroup)
		{
			return pageGroup.Username != _Principal.Identity.Name;
		}

		public Universum.Model.Domain.Classes.PageGroup GetUncategorizedPageGroupByClassId(Guid id)
		{
			var uncategorized = _Repository.Query(new UncategorizedPageGroupByClassId(id)).FirstOrDefault();
			if (uncategorized == null)
			{
				uncategorized = CreateNewPageGroup(id);
				uncategorized.Name = "Uncategorized";
				uncategorized.ParentGroupId = Guid.Empty;
				uncategorized.Order = 1;
				SaveOrUpdate(uncategorized);
			}
			return uncategorized;
		}

		public Universum.Model.Domain.Classes.PageGroup CreateNewPageGroup(
			Guid id)
		{
			var newValue = new Universum.Model.Domain.Classes.PageGroup
			{
				ID = Guid.NewGuid(),
				ClassId = id,
				Username = _Principal.Identity.Name

			};
			return newValue;
		}


		public IList<Universum.Model.Domain.Classes.PageGroup> GetPageGroupsByClassId(Guid id)
		{
			return _Repository.Query(new PageGroupByClassId(id)).ToList();
		}


		public Universum.Model.Domain.Classes.PageGroup GetPageGroupById(Guid guid)
		{
			return _Repository.Load<PageGroup>(guid);
		}




		public void Remove(PageGroup entity)
		{
			List<PageGroup> pageGroupsAttachedToEntity = new List<PageGroup>();
			GetAllPageGroupsAttachedTo(entity, ref pageGroupsAttachedToEntity);
			foreach (var item in pageGroupsAttachedToEntity)
			{

				_LabWorkArticleService.RemoveByPageGroupId(item.ID);
				_PageArticleService.RemoveByPageGroupId(item.ID);

				_Repository.Remove(item);
			}
			_LabWorkArticleService.RemoveByPageGroupId(entity.ID);
			_PageArticleService.RemoveByPageGroupId(entity.ID);
			_Repository.Remove(entity);

		}

		private void GetAllPageGroupsAttachedTo(PageGroup entity, ref List<PageGroup> pages)
		{
			var attached = _Repository.Query(new PageGroupsByClassIdAndParentGroupId(entity.ClassId, entity.ID));
			foreach (var item in attached)
			{
				pages.Add(item);
				GetAllPageGroupsAttachedTo(item, ref pages);
			}


		}

		#endregion




		public void RemoveByClassId(Guid classId)
		{
			var pageGroups = _Repository.Query(new PageGroupByClassId(classId));
			foreach (var pageGroup in pageGroups)
			{				
				//_Repository.Remove(pageGroup);
				Remove(pageGroup);
			}
		}






		public IQueryable<PageGroup> GetPageGroupsByClassIdAndParentGroupId(Guid classId, Guid pageGroupId)
		{
			return _Repository.Query(new PageGroupsByClassIdAndParentGroupId(classId, pageGroupId));
		}

		public void LevelDown(PageGroup pageGroup)
		{


			int count = GetPageGroupsByClassIdAndParentGroupId(
						pageGroup.ClassId,
						pageGroup.ParentGroupId).Count();


			if (pageGroup.Order < count)
			{
				MovePageGroupsDown(pageGroup);
				pageGroup.Order += 1;
				_Repository.SaveOrUpdate(pageGroup);
			}

		}

		private void MovePageGroupsDown(PageGroup pageGroup)
		{
			var nextPageGroups = GetPageGroupsByClassIdAndParentGroupId(pageGroup.ClassId, pageGroup.ParentGroupId).Where(it => it.Order == pageGroup.Order + 1);


			if (null != nextPageGroups)
			{
				foreach (var nextPageGroup in nextPageGroups)
				{
					nextPageGroup.Order -= 1;
					_Repository.SaveOrUpdate(nextPageGroup);
				}
			}
		}

		public void LevelUp(PageGroup pageGroup)
		{
			if (pageGroup.Order > 1)
			{
				MovePageGroupsUp(pageGroup);
				pageGroup.Order -= 1;
				_Repository.SaveOrUpdate(pageGroup);

			}


		}

		private void MovePageGroupsUp(PageGroup pageGroup)
		{
			var previousPageGroups = GetPageGroupsByClassIdAndParentGroupId(
							pageGroup.ClassId,
							pageGroup.ParentGroupId)
							.Where(it => it.Order == pageGroup.Order - 1)
							;
			if (previousPageGroups != null)
			{
				foreach (var previousPageGroup in previousPageGroups)
				{
					previousPageGroup.Order += 1;
					_Repository.SaveOrUpdate(previousPageGroup);
				}
			}
		}


	}
}
